package com.thinkjoy.service;

import com.thinkjoy.Main;
import com.thinkjoy.entity.DeployEntity;
import com.thinkjoy.util.ConsoleHandle;
import com.thinkjoy.util.PathHandle;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * Created by shaojun on 8.21 021.
 */
public abstract class DeployAbstract {

    /**
     * 备份实例
     */
    static DeployEntity deployEntity = new DeployEntity();

    /**
     * 初始化备份实例、初始化日志
     */
    static {
        // 加载color eggs
        InputStream inputStream = Main.class.getResourceAsStream("/coloreggs.properties");
        Properties properties = new Properties();
        String logFileName = "deploy.log";
        try {
            List<String> colorEggs = new ArrayList<>();
            properties.load(new InputStreamReader(inputStream, "utf-8"));
            for (String key : properties.stringPropertyNames()) {
                colorEggs.add(properties.getProperty(key));
            }
            logFileName = colorEggs.get(new Random().nextInt(colorEggs.size())) + ".log";
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            deployEntity.setLogFileName(logFileName);
        }

        // 输入部署目标路径，获取项目名称
        System.out.println("\n################### 请输入部署[目标]文件夹绝对路径： ###################");
        String deployTargetPath = ConsoleHandle.inputDirectoryPath();
        File deployTarget = new File(deployTargetPath);
        String projectName = deployTarget.getName();
        deployEntity.setProjectName(projectName);
        if (StringUtils.isBlank(projectName)) {
            System.out.println("部署目录中获取项目名称失败，很难失败吧！");
            System.exit(0);
        }
        deployEntity.setDeployTarget(deployTarget);

        // 备份目录
        String dateTime = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
        String backupDir = PathHandle.getRelativePath() + File.separator + "backup" + File.separator + projectName + File.separator + dateTime;
        deployEntity.setBackupDir(backupDir);

        /**
         * 将日志输出到备份目录
         */
        System.setProperty("log.dir", backupDir);
        System.setProperty("log.file", logFileName);
    }
    static final Logger logger = Logger.getLogger(DeployAbstract.class.getName());

    /**
     * 执行部署
     */
    public void execute() {
        logger.info("=======================================================================================");
        logger.info("======================================= start =========================================");
        logger.info("=======================================================================================");

        try {
            logger.info("\n\n\n\n===================================================== 第一步：读取部署文件 =======================================================");
            // 输入部署文件名称
            inputDeploySourceName();
            // 扫描部署文件、并且读取进缓存中
            Map<String, File> fileMap = readDeployFiles(deployEntity.getDeploySource());
            if (!confimContinue())
                return;


            logger.info("\n\n\n\n===================================================== 第二步：备份目标 =======================================================");
            // 备份文件
            backupTarget(fileMap);
            if (!confimContinue())
                return;


            logger.info("\n\n\n\n===================================================== 第三步：执行部署 =======================================================");
            // 执行部署
            executeDeply(fileMap);

        } catch (Exception e) {
            e.printStackTrace();
            logger.error("执行过程中出现异常！", e);
        } finally {
            // 结束信息，日志打印
            if (deployEntity.getSuccessCount() == deployEntity.getDeployCount()) {
                logger.info("\n\n################################ 部署成功！ ################################");
            } else {
                logger.error("\n\n################################ 异常！！部署的数量与成功的数量不符！ ################################");
            }
            logger.info("读取部署文件数量：" + deployEntity.getDeployCount());
            logger.info("成功部署文件数量：" + deployEntity.getSuccessCount());
            logger.info("备份目标文件数量：" + deployEntity.getBackupCount());

            logger.info("=======================================================================================");
            logger.info("======================================== end ==========================================");
            logger.info("=======================================================================================");
        }
    }

    /**
     * 输入部署文件夹名称
     */
    public abstract void inputDeploySourceName() throws IOException;

    /**
     * 读取需要部署的文件信息
     *
     * @param deploySource
     * @return
     */
    public abstract Map<String, File> readDeployFiles(File deploySource);

    /**
     * 备份目标文件
     *
     * @param deloyDataMap 部署信息Map
     */
    public abstract void backupTarget(Map<String, File> deloyDataMap) throws IOException;

    /**
     * 确认是否继续提示
     *
     * @return
     * @throws IOException
     * @throws InterruptedException
     */
    abstract boolean confimContinue() throws IOException, InterruptedException;

    /**
     * 执行部署
     */
    public abstract void executeDeply(Map<String, File> fileMap) throws IOException;

}
